class MyTools{

	static encode(text) {
		let passwd = ""
		for (let i of text){
			let cur = Random.randint(0, 26);
			let cur_code = String.fromCharCode(97 + cur);
			passwd += String.fromCharCode(i.charCodeAt() + cur) + cur_code;
		}
    	return passwd
	}

	static decode(passwd) {
		let text = ""
		for (let i = 0; i < passwd.length; i += 2){
			let cur = passwd[i + 1].charCodeAt() - 97;
			text += String.fromCharCode(passwd[i].charCodeAt() - cur);
		}
		return text;
	}


    static mapLength(map){
        var len = 0;
        for (let i of map){
            len++;
        }
        return len
    }

    static ord(character){
        if (character.length === 1 && character.__proto__ === String.prototype){
            return character.charCodeAt()
        }
        throw new Error("\"character\" must be A character")
    }

    static chr(charCode){
        return String.fromCharCode(charCode)
    }

    static sort(arr){
        var x;
        var result = new List(arr);
        for (let i = result.array().length - 1; i > 0; i--){
            for (let j = 0; j < i; j++){
                if (result.array()[j] > result.array()[j+1]){
                    x = result.array()[j];
                    result.set(j, result.array()[j+1]);
                    result.set(j+1, x);
                }
            }
        }
        return result.array();
        
    }

    static isIterable(obj){
        var result = true
        try{
            for (let i of obj){
                break
            }
        }catch(TypeError){
            result = false
        }
        return result
    }


    static getBig(x, y){
        if (typeof(x) != "number" | typeof(y) != "number"){
            throw new Error("Need to int...");
        }
        return x > y ? x: y;
    }


    static floatMul(number, n){
        // if (!new List(String(n)).contains(".")){
        //     let res = number
        //     for (let i = 0; i < n - 1; i++){
        //         res = MyTools.floatAdd(res, number)
        //     }
        //     return res
        // }
        let number_float = String(number).split(".")[1]? String(number).split(".")[1].length: 0
        let n_float = String(n).split(".")[1]? String(n).split(".")[1].length: 0
    
        function mul_ten(number, n){
            let res = String(number)
            if (res.indexOf(".") === -1){
                res += "."
            }
            res = res + "00000000000000000000000000000000"
            let temp = new List(res)
            let zero_index = temp.indexOf(".")
            let final_zero_index = zero_index + n
            temp.delete(["."])
            temp.insert(final_zero_index - 1, ".")
            return parseInt(temp.outString())    
        }
        let res = new List(String(mul_ten(number, number_float) * mul_ten(n, n_float)))
        let max_float = number_float + n_float
        if (res.length() <= max_float){
            res.reversed()
            for (let i = 0; i < max_float - res.length() + 2; i++){
                res.append("0")
            }
            res.insert(max_float - 1, ".")
            res.reversed()
            return parseFloat(res.outString())
        }else {
            res.reversed()
            res.insert(max_float - 1, ".")
            res.reversed()
            
            return parseFloat(res.outString())
        }
    }

    static floatAdd(x, y) {
        let x_float = 0
        let y_float = 0
        let x_add = false, y_add = false
        for (let i of String(x)){
            if (x_add){
                x_float++
            }
            if (i === "."){
                x_add = true
            }
        }

        for (let i of String(y)){
            
            if (y_add){
                y_float++
            }
            if (i === "."){
                y_add = true
            }
        }
    
        let max_float = x_float > y_float? x_float: y_float
        function mul_ten(number, n){
            let res = String(number)
            if (res.indexOf(".") === -1){
                res += "."
            }
            res = res + "00000000000000000000000000000000"
            let temp = new List(res)
            let zero_index = temp.indexOf(".")
            let final_zero_index = zero_index + n
            temp.delete(["."])
            temp.insert(final_zero_index - 1, ".")
            return parseInt(temp.outString())    
        }
        let x_mul = mul_ten(x, max_float)
        let y_mul = mul_ten(y, max_float)
        if (String(x_mul).length < String(y_mul).length){
            let temp = String(x_mul)
            while (temp.length < String(y_mul).length){
                temp += "0"
            }
        }
        if (String(y_mul).length < String(x_mul).length){
            let temp = String(y_mul)
            while (temp.length < String(x_mul).length){
                temp += "0"
            }
        }
        let res = x_mul + y_mul
        let str_res = new List(String(res))
        if (str_res.length() <= max_float){
            for (let i = 0; i <= max_float - str_res.length() + 1; i++){
                str_res.unshift("0")
            }
        }
        for (let i = 0; i < max_float; i++){
            str_res.unshift("0")
        }
        str_res.insert(str_res.length() - max_float - 1, ".")
        // if (str_res.indexOf("-")){
        //     str_res.delete(["-"])
        //     str_res.unshift("-")
        // }
        return parseFloat(str_res.outString())
        
    }


    static isTheArray(obj){
        var result = false;
        if (obj.__proto__ === new Array().__proto__){
            result = true;
        }
        return result;
    }

    static typeEquals(x, y){
        var result = false;
        if (x.__proto__ === y.__proto__){
            result = true;
        }
        return result;
    }

    static eachPrint(array){
        for (let i = 0; i < array.length; i++){
            this.print(array[i]);
        }
    }

    static print(...objs){
        for (let i of objs){
            console.log(i);
            
        }
    }
    
    static addZero(text,num){
        var zeroLength = num - String(text).length;
        var result = "";
        for (let i = 0; i < zeroLength; i++){
            result += "0";
        }
        result += String(text);
        return result;
    }

    static stringToList(str){
        var result = new List([]);
        for (let i of str){
            result.append(i);
        }
        return result;
    }
    
    static range(start, stop){
        if (stop === undefined){
            stop = start
            start = 0
        }
        var array = [];
        var s = start;
        while (s < stop){
            array.push(s);
            s += 1;
        }
        return array
    }



}

class List{
    #array
    #initial
    constructor(iterable){
        if (arguments.length == 0){
            this.#array = new Array();
        // 判断对象是否可迭代(其实不是很严谨这样判断，可以尝试用for来判断)
        }else if (typeof(iterable[Symbol.iterator]) === "function"){
            this.#array = new Array();
            for (let i of iterable){
                this.push(i)
            }
        }
        else if (iterable.__proto__ != new Array().__proto__){
            // var type = String(typeof(array));
            // throw new Error(`TypeError: need to get an \"Array\", but get an \"${type}\"`)
            this.#array = [iterable]
        }else{
            this.#array = iterable;
        }
        this.#initial = []
        for (let i of this.#array){
            this.#initial.push(i)
        }

        Object.defineProperty(this, Symbol.iterator, {
            value: function() {
                let index = 0;
                let arr = this.#array;
                return {
                    next() {
                        return {
                            value: arr[index++],
                            done: index > arr.length
                        }
                    }
                }
            }
        })
        
    }

    static forflat(array){
        let result = []
        for (let i of array){
            if (i.__proto__ != Array.prototype){
                result.push(i)
            }else{
                for (let j of List.forflat(i)){
                    result.push(j)
                }
            }
        }
        return result
    }

    map(callbackfn){
        if (!callbackfn)throw new Error("The function needs a callback function...")
        let result = []
        let all_is_invalid = true
        let null_num = 0
        let undefined_num = 0
        let all_type = null
        function dis(array){
            if (array.__proto__ != Array.prototype){
                return callbackfn(array)
            }
            let res = []
            for (let i of array){
                if (i.__proto__ === Array.prototype){
                    let current = dis(i)
                    res.push(current)
                    current === null? null_num++: undefined_num++
                    if (current != null && current != undefined){
                        all_is_invalid = false
                    }
                    continue
                }
                res.push(callbackfn(i))
            }
            return res
        }
        for (let i of this.#array){
            if (dis(i) && all_is_invalid){
                all_is_invalid = false
            }
            result.push(dis(i))
        }
        if (!all_is_invalid){
            return new List(result)
        }else{
            all_type = result[0] === null? null: undefined
            return `null(${null_num}), undefined(${undefined_num})`
        }
    }

    reset(){
        this.#array = this.#initial
    }

    indexOf(ele){
        var result = 0
        for (let i in this.#array){
            if (Array.isArray(ele) && Array.isArray(this.#array[parseInt(i)])){
                if (new List(ele).absEquals(new List(this.#array[parseInt(i)]))){
                    return parseInt(i)
                }
            }else if (this.#array[parseInt(i)] === ele){
                return parseInt(i)
            }
        }
        return false
    }

    array(){
        return this.#array;
    }

    length(){

        return this.#array.length;
    }

    forEach(func){
        for (let i of this.array()){
            func(i)
        }
    }

    absEquals(listB){
        if (listB.__proto__ != this.__proto__){
            throw new Error("The types of \"listB\" must be \"List\"")
        }

        var result = true
        var x = this.flat(true)
        var y = listB.flat(true)

        if (x.length != y.length){
            return false
        }
        for (let i in x){
            if (x[parseInt(i)] != y[parseInt(i)]){
                return false
            }
        }
        return true
    }

    equals(listB){
        if (listB.__proto__ != this.__proto__){
            throw new Error("The types of \"listB\" must be \"List\"")
        }
        var result = true
        var ele_count_this = this.elementCount()
        var ele_count_listB = listB.elementCount()
        for (let i of new List(ele_count_this.keys()).array()){
            if (ele_count_this.get(i) != ele_count_listB.get(i)){
                result = false
                break
            }
        }
        return result

    }

    // 将列表转换为一维列表, 如果"change"为true, 将改变原列表, "returns"为true, 将返回转换后的列表
    flat(returns, change){
        if (returns === undefined){
            returns = false
        }
        if (change === undefined){
            change = false
        }
        var result = new List()
        for (let i of this.#array){
            if (Array.isArray(i)){
                result.append('Array:')
                result.join(new List(new List(i).flat(true)))
                result.append(":Array")
                continue
            }
            result.append(i)
        }

        if (change === true){
            this.#array = result.array()
        }

        if (returns === true){
            return result.array()
        }
    }

    // outString(){
    //     var result = ""
    //     result += "{"
    //     for (let i in this.#array){
    //         if (parseInt(i) === this.#array.length - 1){
    //             result += this.#array[parseInt(i)]
    //             continue
    //         }
    //         result += this.#array[parseInt(i)]
    //         result += ", "
    //     }
    //     result += "}"
    //     return result

    // }

    outString(){
        let arr = List.forflat(this.#array)
        let res = ""
        for (let i of arr){
            res += i
        }
        return res
    }

    showItems(maximum){
        var isFlat = true
        var result = ""
        for (let i of this.#array){
            if (Array.isArray(i)){
                isFlat = false
                break
            }
        }

        function showMap(map){
            let index = 0
            let result = ""
            result += "("
            for (let j of map){
                if (index === MyTools.mapLength(map) - 1){
                    let key = j[0]
                    let value = j[1]
                    let keyType = typeof key
                    let valueType = typeof value
                    if (key.__proto__ === Array.prototype){
                        key = new List(key).showItems()
                        keyType = "Array"
                    }else if (key.__proto__ === String.prototype){
                        key = "\"" + key + "\""
                    }else if (typeof key === "undefined"){
                        key = "undefined"
                        keyType = "und"
                    }else if (key.__proto__ === Map.prototype){
                        key = showMap(key)
                        keyType = "map"
                    }
        
                    if (value.__proto__ === Array.prototype){
                        value = new List(value).showItems()
                        valueType = "Array"
                    }else if (typeof value === "undefined"){
                        value = "undefined"
                        valueType = "und"
                    }else if (value.__proto__ === String.prototype){
                        value = "\"" + value + "\""
                    }else if (value.__proto__ === Map.prototype){
                        value = showMap(value)
                        valueType = "map"
                    }
        
                    switch (keyType){
                        case "string":
                            // keyType = "str"
                            keyType = ""
                            break
                        case "number":
                            // keyType = "num"
                            keyType = ""
                            break
                        case "boolean":
                            keyType = "bool"
                            break
                        case "Array":
                            keyType = "arr"
                            break
                    }
                    switch (valueType){
                        case "string":
                            // valueType = "str"
                            valueType = ""
                            break
                        case "number":
                            // valueType = "num"
                            valueType = ""
                            break
                        case "boolean":
                            valueType = "bool"
                            break
                        case "Array":
                            valueType = "arr"
                            break
                    }
                    if (keyType === ""){
                        result += key + " -> "
                    }else{
                        result += `${keyType}: ${key} -> `
                    }
                    if (valueType === ""){
                        result += value
                    }else{
                        result += `${valueType}: ${value}`
                    }
                    
                    continue
                    
                }
                let key = j[0]
                let value = j[1]
                let keyType = typeof key
                let valueType = typeof value
                if (key.__proto__ === Array.prototype){
                    key = new List(key).showItems()
                    keyType = "Array"
                }else if (key.__proto__ === String.prototype){
                    key = "\"" + key + "\""
                }else if (typeof key === "undefined"){
                    key = "undefined"
                    keyType = "und"
                }else if (key.__proto__ === Map.prototype){
                    key = showMap(key)
                    keyType = "map"
                }
        
                if (value.__proto__ === Array.prototype){
                    value = new List(value).showItems()
                    valueType = "Array"
                }else if (typeof value === "undefined"){
                    value = "undefined"
                    valueType = "und"
                }else if (value.__proto__ === String.prototype){
                    value = "\"" + value + "\""
                }else if (value.__proto__ === Map.prototype){
                    value = showMap(value)
                    valueType = "map"
                }
        
                switch (keyType){
                    case "string":
                        // keyType = "str"
                        keyType = ""
                        break
                    case "number":
                        // keyType = "num"
                        keyType = ""
                        break
                    case "boolean":
                        keyType = "bool"
                        break
                    case "Array":
                        keyType = "arr"
                        break
                }
                switch (valueType){
                    case "string":
                        // valueType = "str"
                        valueType = ""
                        break
                    case "number":
                        // valueType = "num"
                        valueType = ""
                        break
                    case "boolean":
                        valueType = "bool"
                        break
                    case "Array":
                        valueType = "arr"
                        break
                }
                if (keyType === ""){
                    result += key + " -> "
                }else{
                    result += `${keyType}: ${key} -> `
                }
                if (valueType === ""){
                    result += value + ", "
                }else{
                    result += `${valueType}: ${value}, `
                }
        
                index++;
            }
            result += ")"
            return result
        }

        if (isFlat){
            result += "[ "
            for (let i = 0; i < this.#array.length; i++){
                if (i === this.#array.length - 1){
                    if (this.#array[i].__proto__ === String.prototype){
                        result += "\"" + this.#array[i] + "\""
                        continue
                    }else if (this.#array[i].__proto__ === Map.prototype){
                        let index = 0
                        result += "map: ("
                        for (let j of this.#array[i]){
                            if (index === MyTools.mapLength(this.#array[i]) - 1){
                                let key = j[0]
                                let value = j[1]
                                let keyType = typeof key
                                let valueType = typeof value
                                if (key.__proto__ === Array.prototype){
                                    key = new List(key).showItems()
                                    keyType = "Array"
                                }else if (key.__proto__ === String.prototype){
                                    key = "\"" + key + "\""
                                }else if (typeof key === "undefined"){
                                    key = "undefined"
                                    keyType = "und"
                                }else if (key.__proto__ === Map.prototype){
                                    key = showMap(key)
                                    keyType = "map"
                                }
    
                                if (value.__proto__ === Array.prototype){
                                    value = new List(value).showItems()
                                    valueType = "Array"
                                }else if (typeof value === "undefined"){
                                    value = "undefined"
                                    valueType = "und"
                                }else if (value.__proto__ === String.prototype){
                                    value = "\"" + value + "\""
                                }else if (value.__proto__ === Map.prototype){
                                    value = showMap(value)
                                    valueType = "map"
                                }

                                switch (keyType){
                                    case "string":
                                        // keyType = "str"
                                        keyType = ""
                                        break
                                    case "number":
                                        // keyType = "num"
                                        keyType = ""
                                        break
                                    case "boolean":
                                        keyType = "bool"
                                        break
                                    case "Array":
                                        keyType = "arr"
                                        break
                                }
                                switch (valueType){
                                    case "string":
                                        // valueType = "str"
                                        valueType = ""
                                        break
                                    case "number":
                                        // valueType = "num"
                                        valueType = ""
                                        break
                                    case "boolean":
                                        valueType = "bool"
                                        break
                                    case "Array":
                                        valueType = "arr"
                                        break
                                }
                                if (keyType === ""){
                                    result += key + " -> "
                                }else{
                                    result += `${keyType}: ${key} -> `
                                }
                                if (valueType === ""){
                                    result += value
                                }else{
                                    result += `${valueType}: ${value}`
                                }
                                continue
                            }
                            let key = j[0]
                            let value = j[1]
                            let keyType = typeof key
                            let valueType = typeof value
                            if (key.__proto__ === Array.prototype){
                                key = new List(key).showItems()
                                keyType = "Array"
                            }else if (key.__proto__ === String.prototype){
                                key = "\"" + key + "\""
                            }else if (typeof key === "undefined"){
                                key = "undefined"
                                keyType = "und"
                            }else if (key.__proto__ === Map.prototype){
                                key = showMap(key)
                                keyType = "map"
                            }

                            if (value.__proto__ === Array.prototype){
                                value = new List(value).showItems()
                                valueType = "Array"
                            }else if (typeof value === "undefined"){
                                value = "undefined"
                                valueType = "und"
                            }else if (value.__proto__ === String.prototype){
                                value = "\"" + value + "\""
                            }else if (value.__proto__ === Map.prototype){
                                value = showMap(value)
                                valueType = "map"
                            }

                            switch (keyType){
                                case "string":
                                    // keyType = "str"
                                    keyType = ""
                                    break
                                case "number":
                                    // keyType = "num"
                                    keyType = ""
                                    break
                                case "boolean":
                                    keyType = "bool"
                                    break
                                case "Array":
                                    keyType = "arr"
                                    break
                            }
                            switch (valueType){
                                case "string":
                                    // valueType = "str"
                                    valueType = ""
                                    break
                                case "number":
                                    // valueType = "num"
                                    valueType = ""
                                    break
                                case "boolean":
                                    valueType = "bool"
                                    break
                                case "Array":
                                    valueType = "arr"
                                    break
                            }
                            if (keyType === ""){
                                result += key + " -> "
                            }else{
                                result += `${keyType}: ${key} -> `
                            }
                            if (valueType === ""){
                                result += value + ", "
                            }else{
                                result += `${valueType}: ${value}, `
                            }

                            index++;
                        }
                        result += ")"
                        continue
                    }
                    result += this.#array[i]
                    continue
                }
                if (this.#array[i].__proto__ === String.prototype){
                    result += "\"" + this.#array[i] + "\", "
                    continue
                }else if (this.#array[i].__proto__ === Map.prototype){
                    let index = 0
                    result += "map: ("
                    for (let j of this.#array[i]){
                        if (index === MyTools.mapLength(this.#array[i]) - 1){
                            let key = j[0]
                            let value = j[1]
                            let keyType = typeof key
                            let valueType = typeof value
                            if (key.__proto__ === Array.prototype){
                                key = new List(key).showItems()
                                keyType = "Array"
                            }else if (key.__proto__ === String.prototype){
                                key = "\"" + key + "\""
                            }else if (typeof key === "undefined"){
                                key = "undefined"
                                keyType = "und"
                            }else if (key.__proto__ === Map.prototype){
                                key = showMap(key)
                                keyType = "map"
                            }

                            if (value.__proto__ === Array.prototype){
                                value = new List(value).showItems()
                                valueType = "Array"
                            }else if (typeof value === "undefined"){
                                value = "undefined"
                                valueType = "und"
                            }else if (value.__proto__ === String.prototype){
                                value = "\"" + value + "\""
                            }else if (value.__proto__ === Map.prototype){
                                value = showMap(value)
                                valueType = "map"
                            }

                            switch (keyType){
                                case "string":
                                    // keyType = "str"
                                    keyType = ""
                                    break
                                case "number":
                                    // keyType = "num"
                                    keyType = ""
                                    break
                                case "boolean":
                                    keyType = "bool"
                                    break
                                case "Array":
                                    keyType = "arr"
                                    break
                            }
                            switch (valueType){
                                case "string":
                                    // valueType = "str"
                                    valueType = ""
                                    break
                                case "number":
                                    // valueType = "num"
                                    valueType = ""
                                    break
                                case "boolean":
                                    valueType = "bool"
                                    break
                                case "Array":
                                    valueType = "arr"
                                    break
                            }
                            if (keyType === ""){
                                result += key + " -> "
                            }else{
                                result += `${keyType}: ${key} -> `
                            }
                            if (valueType === ""){
                                result += value
                            }else{
                                result += `${valueType}: ${value}`
                            }
                            continue
                        }
                        let key = j[0]
                        let value = j[1]
                        let keyType = typeof key
                        let valueType = typeof value
                        if (key.__proto__ === Array.prototype){
                            key = new List(key).showItems()
                            keyType = "Array"
                        }else if (key.__proto__ === String.prototype){
                            key = "\"" + key + "\""
                        }else if (typeof key === "undefined"){
                            key = "undefined"
                            keyType = "und"
                        }else if (key.__proto__ === Map.prototype){
                            key = showMap(key)
                            keyType = "map"
                        }

                        if (value.__proto__ === Array.prototype){
                            value = new List(value).showItems()
                            valueType = "Array"
                        }else if (typeof value === "undefined"){
                            value = "undefined"
                            valueType = "und"
                        }else if (value.__proto__ === String.prototype){
                            value = "\"" + value + "\""
                        }else if (value.__proto__ === Map.prototype){
                            value = showMap(value)
                            valueType = "map"
                        }

                        switch (keyType){
                            case "string":
                                // keyType = "str"
                                keyType = ""
                                break
                            case "number":
                                // keyType = "num"
                                keyType = ""
                                break
                            case "boolean":
                                keyType = "bool"
                                break
                            case "Array":
                                keyType = "arr"
                                break
                        }
                        switch (valueType){
                            case "string":
                                // valueType = "str"
                                valueType = ""
                                break
                            case "number":
                                // valueType = "num"
                                valueType = ""
                                break
                            case "boolean":
                                valueType = "bool"
                                break
                            case "Array":
                                valueType = "arr"
                                break
                        }
                        if (keyType === ""){
                            result += key + " -> "
                        }else{
                            result += `${keyType}: ${key} -> `
                        }
                        if (valueType === ""){
                            result += value + ", "
                        }else{
                            result += `${valueType}: ${value}, `
                        }

                        index++;
                    }
                    result += "), "
                    continue
                }
                result += this.#array[i]
                result += ", "
            }
            result += " ]"
            if (maximum != undefined && (typeof(maximum) === "number" && new List(String(maximum)).contains(".") === undefined)){
                if (maximum >= this.#array.length){
                    return result
                }else{
                    let slice = new List(this.slice(0, maximum))
                    return slice.showItems()
                }
            }
            return result
        }else {
            result += "[ "
            for (let i = 0; i < this.#array.length; i++){
                if (i === this.#array.length - 1){
                    if (Array.isArray(this.#array[i])){
                        result += new List(this.#array[i]).showItems()
                        continue
                    }else if (this.#array[i].__proto__ === Map.prototype){
                        let index = 0
                        result += "map: ("
                        for (let j of this.#array[i]){
                            if (index === MyTools.mapLength(this.#array[i]) - 1){
                                let key = j[0]
                                let value = j[1]
                                let keyType = typeof key
                                let valueType = typeof value
                                if (key.__proto__ === Array.prototype){
                                    key = new List(key).showItems()
                                    keyType = "Array"
                                }else if (key.__proto__ === String.prototype){
                                    key = "\"" + key + "\""
                                }else if (typeof key === "undefined"){
                                    key = "undefined"
                                    keyType = "und"
                                }else if (key.__proto__ === Map.prototype){
                                    key = showMap(key)
                                    keyType = "map"
                                }
    
                                if (value.__proto__ === Array.prototype){
                                    value = new List(value).showItems()
                                    valueType = "Array"
                                }else if (typeof value === "undefined"){
                                    value = "undefined"
                                    valueType = "und"
                                }else if (value.__proto__ === String.prototype){
                                    value = "\"" + value + "\""
                                }else if (value.__proto__ === Map.prototype){
                                    value = showMap(value)
                                    valueType = "map"
                                }

                                switch (keyType){
                                    case "string":
                                        // keyType = "str"
                                        keyType = ""
                                        break
                                    case "number":
                                        // keyType = "num"
                                        keyType = ""
                                        break
                                    case "boolean":
                                        keyType = "bool"
                                        break
                                    case "Array":
                                        keyType = "arr"
                                        break
                                }
                                switch (valueType){
                                    case "string":
                                        // valueType = "str"
                                        valueType = ""
                                        break
                                    case "number":
                                        // valueType = "num"
                                        valueType = ""
                                        break
                                    case "boolean":
                                        valueType = "bool"
                                        break
                                    case "Array":
                                        valueType = "arr"
                                        break
                                }
                                if (keyType === ""){
                                    result += key + " -> "
                                }else{
                                    result += `${keyType}: ${key} -> `
                                }
                                if (valueType === ""){
                                    result += value
                                }else{
                                    result += `${valueType}: ${value}`
                                }
                                continue
                            }
                            let key = j[0]
                            let value = j[1]
                            let keyType = typeof key
                            let valueType = typeof value
                            if (key.__proto__ === Array.prototype){
                                    key = new List(key).showItems()
                                    keyType = "Array"
                                }else if (key.__proto__ === String.prototype){
                                    key = "\"" + key + "\""
                                }else if (typeof key === "undefined"){
                                    key = "undefined"
                                    keyType = "und"
                                }else if (key.__proto__ === Map.prototype){
                                    key = showMap(key)
                                    keyType = "map"
                                }
    
                                if (value.__proto__ === Array.prototype){
                                    value = new List(value).showItems()
                                    valueType = "Array"
                                }else if (typeof value === "undefined"){
                                    value = "undefined"
                                    valueType = "und"
                                }else if (value.__proto__ === String.prototype){
                                    value = "\"" + value + "\""
                                }else if (value.__proto__ === Map.prototype){
                                    value = showMap(value)
                                    valueType = "map"
                                }

                                switch (keyType){
                                    case "string":
                                        // keyType = "str"
                                        keyType = ""
                                        break
                                    case "number":
                                        // keyType = "num"
                                        keyType = ""
                                        break
                                    case "boolean":
                                        keyType = "bool"
                                        break
                                    case "Array":
                                        keyType = "arr"
                                        break
                                }
                                switch (valueType){
                                    case "string":
                                        // valueType = "str"
                                        valueType = ""
                                        break
                                    case "number":
                                        // valueType = "num"
                                        valueType = ""
                                        break
                                    case "boolean":
                                        valueType = "bool"
                                        break
                                    case "Array":
                                        valueType = "arr"
                                        break
                                }
                                if (keyType === ""){
                                    result += key + " -> "
                                }else{
                                    result += `${keyType}: ${key} -> `
                                }
                                if (valueType === ""){
                                    result += value + ", "
                                }else{
                                    result += `${valueType}: ${value}, `
                                }

                            index++;
                        }
                        result += ")"
                        continue
                    }else if (this.#array[i].__proto__ === String.prototype){
                        result += "\"" + this.#array[i] + "\""
                        continue
                    }
                    result += this.#array[i]
                    continue
                    
                }
                if (Array.isArray(this.#array[i])){
                    result += new List(this.#array[i]).showItems()
                    result += ", "
                    continue
                }else if (this.#array[i].__proto__ === Map.prototype){
                    let index = 0
                    result += "map: ("
                    for (let j of this.#array[i]){
                        if (index === MyTools.mapLength(this.#array[i]) - 1){
                            let key = j[0]
                            let value = j[1]
                            let keyType = typeof key
                            let valueType = typeof value
                            if (key.__proto__ === Array.prototype){
                                key = new List(key).showItems()
                                keyType = "Array"
                            }else if (key.__proto__ === String.prototype){
                                key = "\"" + key + "\""
                            }else if (typeof key === "undefined"){
                                key = "undefined"
                                keyType = "und"
                            }else if (key.__proto__ === Map.prototype){
                                key = showMap(key)
                                keyType = "map"
                            }

                            if (value.__proto__ === Array.prototype){
                                value = new List(value).showItems()
                                valueType = "Array"
                            }else if (typeof value === "undefined"){
                                value = "undefined"
                                valueType = "und"
                            }else if (value.__proto__ === String.prototype){
                                value = "\"" + value + "\""
                            }else if (value.__proto__ === Map.prototype){
                                value = showMap(value)
                                valueType = "map"
                            }

                            switch (keyType){
                                case "string":
                                    // keyType = "str"
                                    keyType = ""
                                    break
                                case "number":
                                    // keyType = "num"
                                    keyType = ""
                                    break
                                case "boolean":
                                    keyType = "bool"
                                    break
                                case "Array":
                                    keyType = "arr"
                                    break
                            }
                            switch (valueType){
                                case "string":
                                    // valueType = "str"
                                    valueType = ""
                                    break
                                case "number":
                                    // valueType = "num"
                                    valueType = ""
                                    break
                                case "boolean":
                                    valueType = "bool"
                                    break
                                case "Array":
                                    valueType = "arr"
                                    break
                            }
                            if (keyType === ""){
                                result += key + " -> "
                            }else{
                                result += `${keyType}: ${key} -> `
                            }
                            if (valueType === ""){
                                result += value
                            }else{
                                result += `${valueType}: ${value}`
                            }
                            continue
                        }
                        let key = j[0]
                        let value = j[1]
                        let keyType = typeof key
                        let valueType = typeof value
                        if (key.__proto__ === Array.prototype){
                            key = new List(key).showItems()
                            keyType = "Array"
                        }else if (key.__proto__ === String.prototype){
                            key = "\"" + key + "\""
                        }else if (typeof key === "undefined"){
                            key = "undefined"
                            keyType = "und"
                        }else if (key.__proto__ === Map.prototype){
                            key = showMap(key)
                            keyType = "map"
                        }

                        if (value.__proto__ === Array.prototype){
                            value = new List(value).showItems()
                            valueType = "Array"
                        }else if (typeof value === "undefined"){
                            value = "undefined"
                            valueType = "und"
                        }else if (value.__proto__ === String.prototype){
                            value = "\"" + value + "\""
                        }else if (value.__proto__ === Map.prototype){
                            value = showMap(value)
                            valueType = "map"
                        }

                        switch (keyType){
                            case "string":
                                // keyType = "str"
                                keyType = ""
                                break
                            case "number":
                                // keyType = "num"
                                keyType = ""
                                break
                            case "boolean":
                                keyType = "bool"
                                break
                            case "Array":
                                keyType = "arr"
                                break
                        }
                        switch (valueType){
                            case "string":
                                // valueType = "str"
                                valueType = ""
                                break
                            case "number":
                                // valueType = "num"
                                valueType = ""
                                break
                            case "boolean":
                                valueType = "bool"
                                break
                            case "Array":
                                valueType = "arr"
                                break
                        }
                        if (keyType === ""){
                            result += key + " -> "
                        }else{
                            result += `${keyType}: ${key} -> `
                        }
                        if (valueType === ""){
                            result += value + ", "
                        }else{
                            result += `${valueType}: ${value}, `
                        }

                        index++;
                    }
                    result += "), "
                    continue
                }else if (this.#array[i].__proto__ === String.prototype){
                    result += "\"" + this.#array[i] + "\", "
                    continue
                }
                result += this.#array[i]
                result += ", "
            }
            result += " ]"
            if (maximum != undefined && (typeof(maximum) === "number" && new List(String(maximum)).contains(".") === undefined)){
                if (maximum >= this.#array.length){
                    return result
                }else{
                    let slice = new List(this.slice(0, maximum))
                    return slice.showItems()
                }
            }
            return result
        }
    }

    // maxDepth(){
    //     var dep = 0
    //     // 判断是否是1维数组/包含数组
    //     let isFlat = true
    //     for (let i of this.#array){
    //         if (Array.isArray(i)){
    //             isFlat = false
    //             break
    //         }
    //     }
    //     if (isFlat){
    //         return 1
    //     }

    //     for (let i = 0; i < this.#array; i++){
    //         console.log(Arrar.isArray(this.#array[i]));
    //         if (!Array.isArray(this.#array[i])){
    //             continue
    //         }
    //         dep += this.maxDepth(this.#array[i])
    //     }
    //     return dep

    // }

    static toString(list){
        let result = "";
        for (let i of list.array()){
            result += i;
        }
        return result;
    }

    get(index){
        return this.#array[index]
    }

    reversed(return_if){
        if (return_if) {
            let result = new List();
            for (let i = this.#array.length - 1; i >= 0; i--){
                result.append(this.#array[i]);
            }
            return result;
        }
        for (let i = 0; i < Math.floor(this.#array.length / 2); i++){
            let temp = this.#array[i];
            let len = this.#array.length;
            // [1, 2, 3, 4, 5]
            this.#array[i] = this.#array[len - i - 1];
            this.#array[len - i - 1] = temp;
        }
    }


    clear(){
        this.#array = [];
    }

    insert(index, ele){
        var result = new List()
        for (let i = 0; i <= index; i++){
            result.append(this.#array[i])
        }
        result.append(ele)
        for (let i = index + 1; i < this.#array.length; i++){
            result.append(this.#array[i])
        }
        this.#array = result.array()
    }

    originalSort(){
        this.#array.sort();
    }

    sort(){
        var x;
        var result = new List(this.#array);
        for (let i = result.array().length - 1; i > 0; i--){
            for (let j = 0; j < i; j++){
                if (result.array()[j] > result.array()[j+1]){
                    x = result.array()[j];
                    result.set(j, result.array()[j+1]);
                    result.set(j+1, x);
                }
            }
        }
        this.#array = result.#array
    }


    append(...obj){
        for (let i of obj){
            this.#array.push(i);
        }
        
    }

    join(listB){
        if (listB.__proto__ != this.__proto__){
            throw new Error("The types of \"listB\" must be \"List\"")
        }
        for (let i of listB.array()){
            this.append(i)
        }
    }


    delete(del_target){
        var final = [];
        var contains = false
        if (!Array.isArray(del_target)){
            var index = parseInt(del_target.split("index->")[1])
            for (let i in this.#array){
                if (parseInt(i) === index){
                    continue
                }
                final.push(this.#array[parseInt(i)])
            }
            this.#array = final
            return undefined
        }
        for (let i of this.#array){
            for (let j of del_target){
                if (j === i){
                    contains = true
                    break
                }
            }
            if (contains === false){
                final.push(i)
            }else {
                contains = false
            }

        }
        this.#array = final;
    }


    pop(){
        return this.#array.pop();
    }
    
    push(obj){
        return this.#array.push(obj);
    }

    shift(){
        return this.#array.shift();
    }

    unshift(obj){
        return this.#array.unshift(obj);
    }

    set(index, obj){
        this.#array[index] = obj;
    }

    slice(start, stop){
        var result = new List();
        if (start < 0 | stop > this.#array.length){
            throw new Error("elementError!!: stop > array.length or start < 0");
        }
        for (let i = 0; i < this.#array.length; i++){
            if (i >= start && i < stop){
                result.append(this.#array[i]);
            }
        }
        return result.array();
    }

    elementCount(){
        var result = new Map()
        var box = []
        var num = 0
        for (let i of this.#array){
            num = 0
            if (box.indexOf(i) === -1){
                box.push(i)
                for (let j of this.#array){
                    if (Array.isArray(i) && new List(i).absEquals(new List(j))){
                        num += 1
                        continue
                    }
                    if (i === j){
                        num += 1
                    }
                }
                if (i.__proto__ === Array.prototype){
                    result.set("Array:" + new List(i).showItems(), num)
                }else if (i.__proto__ === Map.prototype){
                    result.set("Map:" + new List(i).showItems(), num)
                }else {
                    result.set("[ " + String(i) + " ]", num)
                }
                
            }
        }
        return result
    }

    contains(ele, strictForArray){
        var result = 0
        if (strictForArray != undefined && strictForArray != true && strictForArray != false){
            throw new Error("Parameter value error: \"strictForArray\"")
        }
        if (strictForArray === undefined || strictForArray === false){
            for (let i of this.#array){
                // ele是数组
                if (Array.isArray(ele) && new List([ele]).equals(new List([i]))){
                    return result
                }else if (ele.__proto__ === Map.prototype){
                    let map = new List()
                    for (let i of ele){
                        map.append(i)
                    }
                    for (let i of this.#array){
                        if (i.__proto__ === Map.prototype){
                            let current = new List()
                            for (let j of i){
                                current.append(j)
                            }
                            if (map.equals(current)){
                                return result
                            }
                        }
                        result++
                    }

                }else if (i === ele){
                    
                    return result
                }
                result++
            }
        }else if (strictForArray === true){
            for (let i of this.#array){
                // ele是数组
                if (Array.isArray(ele) && new List([ele]).absEquals(new List([i]))){
                    return result
                }else if (ele.__proto__ === Map.prototype){
                    let map = new List()
                    for (let i of ele){
                        map.append(i)
                    }
                    for (let i of this.#array){
                        if (i.__proto__ === Map.prototype){
                            let current = new List()
                            for (let j of i){
                                current.append(j)
                            }
                            if (map.absEquals(current)){
                                return result
                            }
                        }
                        result++
                    }

                }else if (i === ele){
                    return result
                }
                result++;
            }
        }
        
    }

    static getValueByString(target_string){
        if (typeof(target_string) != "string"){
            target_string = String(target_string)
        }
        var result = new List([]);
        for (let i of target_string){
            result.append(i);
        }
        return result;
    }

    toString(){
        var result = "";
        for (let i of this.#array){
            result += i;
        }
        return result;
    }

}


class math{

    static ptgrsTheorem(a, b){
        return Math.pow(Math.pow(a, 2) + Math.pow(b, 2), 0.5)
    }
    
    static toBinary(number){
        if (!number){
            return number
        }
        let result = []
        while (true){
            if (number === 1){
                result.push("1")
                break
            }
            result.push(String(number % 2))
            number = Math.floor(number / 2)
    
        }

        let midline = !(result.length % 2)? "noMidline": Math.floor(result.length / 2)
        if (midline === "noMidline"){
            for (let i = 0; i < result.length / 2; i++){
                let temp = result[i]
                result[i] = result[result.length - (i + 1)]
                result[result.length - (i + 1)] = temp
            }
        }else {
            let count = 0
            while (count <= midline){
                let temp = result[count]
                result[count] = result[result.length - (count + 1)]
                result[result.length - (count + 1)] = temp
                count++
            }
        }
        return result.join("")
    }

    static precision(num, pre, round){
        let str_num = String(num)
        if (!round){
            round = false
        }
        if (pre === 0){
            if (!new List(str_num).contains(".")){
                return num
            }else {
                if (round){
                    let float = String(str_num.split(".")[1][0])
                    if (float >= 5){
                        return Math.floor(num) + 1
                    }
                }
                return Math.floor(num)
            }
        }
        
        if (!new List(str_num).contains(".")){
            let float_length = 0
            str_num += "."
            while (float_length < pre){
                str_num += "0"
                float_length++
            }
            return str_num
        }
        let float_length = str_num.split(".")[1].length
        if (float_length === pre){
            return num
        }else if (float_length < pre){
            while (float_length < pre){
                str_num += "0"
                float_length++
            }
            return str_num
        }else {
            if (round){
                let float_part = str_num.split(".")[1]
                let last = parseInt(float_part[pre])
                let int_part = str_num.split(".")[0] + "."
                let add_part = float_part.slice(0, pre)
                let res = parseFloat(int_part + add_part)
                let temp = "0."
                for (let i = 1; i < pre; i++){
                    temp += "0"
                }
                temp += "1"
                if (last >= 5){
                    res = math.floatCalc(`${res} + ${temp}`)
                }
                return res
            }
            let float_part = str_num.split(".")[1]
            let int_part = str_num.split(".")[0] + "."
            float_part = float_part.slice(0, pre)
            return parseFloat(int_part + float_part)
        }
    }

    // 幂运算
    static pow(num, power){
        if (power === undefined){
            power = 1
        }
        return Math.pow(num, power)
    }

    // 弧度转角度
    static radToAng(rad){
        return rad * 57.29577951308232;
    }

    // 角度转弧度
    static angToRad(angle, pi){
        if (pi === undefined){
            pi = 3.14;
        }
        return angle * pi / 180;
    }

    // 终边相等
    static equalsEndEdge(angle){
        if (angle >= 360){
            return angle % 360;
        }else if (angle < 360){
            return angle - 720;
        }
        
    }

    // 浮点数精确计算
    static floatCalc(expression, float_length, round){
        if (new List(expression).contains(" ")){
            var temp = ""
            for (let i of expression){
                if (i != " "){
                    temp += i
                }
            }
            expression = temp
        }
        var x, y, result, ope;
        var counter = 1;

        if (new List(expression).contains("+") != undefined){
            x = expression.split('+')[0];
            y = expression.split('+')[1];
            ope = '+';

        }else if (new List(expression).contains("*") != undefined){
            x = expression.split('*')[0];
            y = expression.split('*')[1];
            ope = '*';
        }else if (new List(expression).contains("-") != undefined){
            // 负号出现两次
            if (new List(expression).elementCount().get("[-]") === 2){
                // 第一个数是负数
                if (new List(expression).contains("-") === 0){
                    x = expression.split("-")[1]
                    y = expression.split("-")[2]
                    x = `-${x}`
                    ope = '-';
                }else {
                    // 第二个数是负数
                    x = expression.split("-")[0]
                    y = expression.split("-")[2]
                    y = `-${y}`
                    ope = '-';
                }
            }else if (new List(expression).elementCount().get("[-]") === 3){
                ope = '-';
                x = -(expression.split("-")[1])
                y = -(expression.split("-")[3])
            }else {
                x = expression.split('-')[0];
                y = expression.split('-')[1];
                ope = '-';
            }

        }if (new List(expression).contains("/") != undefined){
            x = expression.split('/')[0];
            y = expression.split('/')[1];
            ope = '/';
        }
        // x = parseFloat(x);
        // y = parseFloat(y);
        switch (ope){
            case '+':
                result = MyTools.floatAdd(x, y);
                break;
            case '-':
                result = MyTools.floatAdd(x, -(y))
                break;
            case '*':
                result = MyTools.floatMul(x, y)
                break
            case '/':
                // throw new Error("For some strange reason, division does not support exact calculation");
                result = x / y
        }
        if (float_length === undefined){
            return result;
        }else {
            if (!round){
                return math.precision(result, float_length)
            }else {
                return math.precision(result, float_length, round)
            }
        }
        
    }

    

    static circularAreaByRad(r, pi){
        if (pi === undefined){
            pi = 3.14
        }
        return pi * this.pow(r, 2)
    }

    static circularAreaByDia(d, pi){
        if (pi === undefined){
            pi = 3.14
        }
        return pi * this.pow(d/2, 2)
    }

}

class Random{
    // 随机正整数，参数不能包含负数
    static randPositiveInteger(min, max){
        if (min > max){
            throw new Error("\"min\" should be smaller than \"max\"");
        }else if (min < 0 | max < 0){
            throw new Error("range cannot be less than \"zero\"");
        }

        // 下面这段可以扩大正整数的最大取值范围，但一般用不上，因为默认已经都是一个17位的数了
        // var add = String(Math.random())
        // var add1 = new List(add)
        // add1.delete(["0", "."])
        // var root = Math.random() + add1.toString()

        var root = Math.random()

        root = new List(List.getValueByString(String(root)).slice(2, String(root).length)).toString();
        var num_length = Random.randint(1, String(max).length);
        root = new List(List.getValueByString(root).slice(0, num_length)).toString();
        root = parseInt(root);

        while (root < min | root > max){
            
            // add = String(Math.random())
            // add1 = new List(add)
            // add1.delete(["0", "."])
            // root = Math.random() + add1.toString()

            root = Math.random();

            root = new List(List.getValueByString(String(root)).slice(2, String(root).length)).toString();
            num_length = Random.randint(1, String(max).length);
            root = new List(List.getValueByString(root).slice(0, num_length)).toString();
            root = parseInt(root);

        }
        return root;
    }
    
    // 随机正浮点数，因为基于random函数，故参数同样不能包含负数
    static randPositiveFloat(min, max, float_length){

        if (min > max){
            throw new Error("\"min\" should be smaller than \"max\"");
        }else if (min < 0 | max < 0){
            throw new Error("range cannot be less than \"zero\"");
        }

        if (float_length === undefined){
            float_length = 1;
        }
        var forward_int = String(Random.randPositiveInteger(min, max - 1));
        var float = "";
        for (let i = 0; i < float_length; i++){
            float += String(Random.randPositiveInteger(1, 9));
        }
        var result = forward_int + '.' + float;
        result = parseFloat(result);
        return result;
    }

    // 范围完善的随机数
    static randint(start, stop){
        if (start > stop){
            throw new Error("\"start\" not less than the \"stop\"...")
        }
        // 正整数(包含0)
        if (start >= 0 && stop >= 0){
            if (start === stop){
                return start
            }
            return Random.randPositiveInteger(start, stop)
            
        }

        // 范围是负整数
        // if (start < 0 && stop < 0){
        //     if (start === stop){
        //         return start
        //     }
        //     var temp = start
        //     start = stop
        //     stop = temp
        //     return math.opposite(Random.randint(math.opposite(start), math.opposite(stop)))
        // }
        if (start < 0 && stop < 0){
            if (start === stop){
                return start
            }
            var temp = start
            start = stop
            stop = temp
            return -Random.randint(-start, -stop)
        }

        // 范围是负整数到整数
        if (start < 0 && stop >= 0){
            if (start > stop){
                throw new Error("\"max\" not less than the \"stop\"...")
            }else if (start === stop){
                return start
            }
            return Random.randint(0, 1) == 1? Random.randint(0, stop) : Random.randint(start, -1)

        }
    }

    static randfloat(start, stop, float_length){
        if (start === stop){
            return start
        }

        let int_part = String(Random.randint(start, stop - 1))

        if (!float_length){
            float_length = 1
        }
        let x = ""
        for (let i = 0; i < float_length; i++){
            x += String(Random.randint(0, 9))
        }
        
        let float_part = x
        if (float_part[float_part.length - 1] === "0" || float_part.length < float_length){
            if (float_part[float_part.length - 1] === "0"){
                float_part = float_part.slice(0, float_part.length - 1)
                float_part += String(Random.randint(1, 9))
            }else {
                while (float_part.length < float_length){
                    float_part += String(Random.randint(1, 9))
                }
            }
            
        }
        let res = parseFloat(int_part + "." +float_part)
        if (res > stop){
            res = math.floatCalc(`${res} - 1`)
        }else if (res < start){
            res = math.floatCalc(`${res} + 1`)
        }
        return res
        
    }

    static randChoice(choice_box){
        if (choice_box.__proto__ != new List().__proto__){
            throw new Error("The types of \"choice_box\" must be \"List\"")
        }else if (choice_box.length() === 0){
            return null
        }
        var map = new Map([])
        for (let i = 1; i <= choice_box.length(); i++){
            map.set(i, choice_box.get(i - 1))
        }
        var target = Random.randint(1, choice_box.length())
        return map.get(target)
    }

    static extract(extract_number, from_datas){
        if (from_datas.__proto__ != List.prototype){
            throw new Error("The types of \"choice_box\" must be \"List...\"")
        }
        if (extract_number > from_datas.length()){
            throw new Error("\"extract_number\" must be smaller than \"from_datas.length()\"")
        }
        if (extract_number === from_datas.length()){
            return from_datas
        }
        // var el;
        // var result = new List()
        // while (result.length() < extract_number){
        //     el = Random.randChoice(from_datas)
        //     from_datas.delete([el])
        //     if (result.elementCount(new List([el])) === false){
        //         result.append(el)
        //     }
        // }
        let result = new List();
        while (result.length() < extract_number) {
            let el = Random.randChoice(from_datas)
            if (! result.contains(el, true)) {
                result.append(el);
                from_datas.delete([el]);
            }
        }
        return result.array()
    }
}


class Matrix{
    #array
    #judgeLegitimacy
    constructor(array){

        if (!array){
            this.#array = []
        }else{
            this.#array = []
            for (let i of array){
                if (i.__proto__ === Number.prototype){
                    this.#array.push([i])
                }else{
                    this.#array.push(i)
                }
            }
        }
        
        this.#judgeLegitimacy = function(array){
            let result = true
            for (let i of array){
                if (i.__proto__ === Array.prototype){
                    result = (this.#judgeLegitimacy(i) === true) || false
                }else if (typeof i === "number" || i === "e"){
                    continue
                }else {
                    return false
                }
            }
            return result
        }
        if (!this.#judgeLegitimacy(this.#array)){
            throw new Error("The matrix contains non-numeric objects")
        }
        
    }

    copy(){
        let result = []
        for (let i of this.#array){
            let temp = []
            for (let j of i){
                temp.push(j)
            }
            result.push(temp)
        }
        return new Matrix(result)
    }

    add(matrixB){
        if (!new List(matrixB.shape()).absEquals(new List(this.shape()))){
            throw new Error("The matrix shapes are different...")
        }
        let x_arr = List.forflat(this.#array)
        let y_arr = List.forflat(matrixB.get_array())
        let sum_arr = []
        for (let i = 0; i < x_arr.length; i++){
            sum_arr.push(math.floatCalc(`${x_arr[i]} + ${y_arr[i]}`))
        }
        let counter = 0
        let result = []
        for (let i of this.#array){
            let temp = []
            for (let j = 0; j < i.length; j++){
                temp.push(sum_arr[counter])
                counter++
            }
            result.push(temp)
        }
        return new Matrix(result)
    }

    sub(matrixB){
        if (!new List(matrixB.shape()).absEquals(new List(this.shape()))){
            throw new Error("The matrix shapes are different...")
        }
        let x_arr = List.forflat(this.#array)
        let y_arr = List.forflat(matrixB.get_array())
        let sum_arr = []
        for (let i = 0; i < x_arr.length; i++){
            sum_arr.push(math.floatCalc(`${x_arr[i]} - ${y_arr[i]}`))
        }
        let counter = 0
        let result = []
        for (let i of this.#array){
            let temp = []
            for (let j = 0; j < i.length; j++){
                temp.push(sum_arr[counter])
                counter++
            }
            result.push(temp)
        }
        return new Matrix(result)
    }
    
    mul(matrixB){
        if (!new List(matrixB.shape()).absEquals(new List(this.shape()))){
            throw new Error("The matrix shapes are different...")
        }
        let x_arr = List.forflat(this.#array)
        let y_arr = List.forflat(matrixB.get_array())
        let sum_arr = []
        for (let i = 0; i < x_arr.length; i++){
            sum_arr.push(math.floatCalc(`${x_arr[i]} * ${y_arr[i]}`))
        }
        let counter = 0
        let result = []
        for (let i of this.#array){
            let temp = []
            for (let j = 0; j < i.length; j++){
                temp.push(sum_arr[counter])
                counter++
            }
            result.push(temp)
        }
        return new Matrix(result)
    }

    div(matrixB){
        if (!new List(matrixB.shape()).absEquals(new List(this.shape()))){
            throw new Error("The matrix shapes are different...")
        }
        let x_arr = List.forflat(this.#array)
        let y_arr = List.forflat(matrixB.get_array())
        let sum_arr = []
        for (let i = 0; i < x_arr.length; i++){
            sum_arr.push(x_arr[i] / y_arr[i])
        }
        let counter = 0
        let result = []
        for (let i of this.#array){
            let temp = []
            for (let j = 0; j < i.length; j++){
                temp.push(sum_arr[counter])
                counter++
            }
            result.push(temp)
        }
        return new Matrix(result)
    }

    shape(){
        if (new List(this.#array).absEquals(new List())){
            return [0, 0]
        }
        let height = this.#array.length
        let widths = []
        function deep(array){
            if (array.__proto__ === Number.prototype){
                return 1
            }
            let result = 0
            for (let i of array){
                if (i.__proto__ === Array.prototype){
                    result += deep(i)
                }else{
                    result++
                }
            }
            return result
        }

        for (let i of this.#array){
            widths.push(deep(i))
        }
        let width = widths[0]
        for (let i of widths){
            if (i > width){
                width = i
            }
        }
        return [height, width]
    }

    get_array(){
        return this.#array
    }


    // 重写show()方法
    show(){
        if (new List(this.shape()).absEquals(new List([0, 0]))){
            return "{\n\t[]\n}"
        }
        function max_length(array){
            let length = 1
            for (let i of array){
                if (i.__proto__ === Number.prototype){
                    i = [i]
                }
                if (i.length === 1){
                    let current = String(i[0]).length
                    current > length? length = current: length
                }else {
                    for (let j = 0; j < i.length; j++){
                        let current = String(i[j]).length
                        current > length? length = current: length
                    }
                }
            }
            return length
        }

        let max_len = max_length(this.#array)
        function showItem(array){
            let result = ""
            if (array.length === 1){
                // result = "[ "
                let str_len = new List(String(array[0])).length()
                let str = new List(String(array[0])).reversed(true)
                let temp = ""
                for (let i of str){
                    temp += i
                }
                for (let i = 0; i < max_len - str_len; i++){
                    temp += " "
                }
                temp = new List(temp).reversed(true)
                for (let i of temp){
                    result += i
                }
                // result += " ]"
            }else {
                result += "[ "
                for (let i = 0; i < array.length; i++){
                    if (i != array.length - 1){
                        if (array[i].__proto__ === Array.prototype){
                            result += showItem(array[i]) + ", "
                        }else {
                            let str = new List(String(array[i])).reversed(true)
                            let temp = ""
                            for (let j of str){
                                temp += j
                            }
                            let str_len = temp.length
                            for (let j = 0; j < max_len - str_len; j++){
                                temp += " "
                            }
                            temp = new List(temp).reversed(true)
                            str = ""
                            for (let j of temp){
                                str += j
                            }
                            result += str + ", "
                        }
                        
                    }else {
                        if (array[i].__proto__ === Array.prototype){
                            result += showItem(array[i])
                        }else {
                            let str = new List(String(array[i])).reversed(true)
                            let temp = ""
                            for (let j of str){
                                temp += j
                            }
                            let str_len = temp.length
                            for (let j = 0; j < max_len - str_len; j++){
                                temp += " "
                            }
                            temp = new List(temp).reversed(true)
                            str = ""
                            for (let j of temp){
                                str += j
                            }
                            result += str
                        }
                    }
                }
                result += " ]"
            }
            return result
        }
        let result = "{\n"
        let new_arr = []
        for (let i of this.#array){
            for (let j of i){
                new_arr.push(j)
            }
        }

        let arr = []
        for (let i = 0; i < this.#array.length; i++){
            arr.push(this.#array[i])
        }
        for (let i = 0; i < arr.length; i++){
            arr[i] = List.forflat(arr[i])
        }


        // for (let i = 0; i < this.#array.length; i++){
        //     if (i === this.#array.length - 1){
        //         result += "\t" + showItem(this.#array[i])
        //     }else {
        //         result += "\t" + showItem(this.#array[i]) + "\n\n"
        //     }
        // }
        for (let i = 0; i < arr.length; i++){
            if (i === arr.length - 1){
                result += "\t" + showItem(arr[i])
            }else {
                result += "\t" + showItem(arr[i]) + "\n\n"
            }
        }
        result += "\n}"
        return result
    }

    // 格式化矩阵，空缺的用"e"补全
    format(){
        let result = []
        let temp = []
        let max_width = this.shape()[1]
        for (let i of this.#array){
            let arr = List.forflat(i)
            temp.push(arr)
        }
        
        for (let i of temp){
            while (i.length < max_width){
                i.push("e")
            }
            result.push(i)
        }
        return new Matrix(result)
    }

    static create(value, shape){
        let result = []
        for (let i = 0; i < shape[0]; i++){
            let temp = []
            for (let j = 0; j < shape[1]; j++){
                if (typeof value === "function"){
                    temp.push(value())
                    continue
                }
                temp.push(value)
            }
            result.push(temp)
        }
        return new Matrix(result)
    }

    get(index){
        return this.#array[index[0]][index[1]]
    }

    set(index, value){
        try{
            if (this.#array[index[0]][index[1]] === undefined){
                throw new Error(`index out of range -> [${index[0]} , ${index[1]}]`)
            }
        }catch (TypeError){
            throw new Error(`index out of range -> [${index[0]} , ${index[1]}]`)
        }
        
        this.#array[index[0]][index[1]] = value
    }



    //尝试控制分解深度
    dispose(callbackfn, max_float, rec_array){
        if (max_float === undefined || max_float.__proto__ != Number.prototype){
            max_float = 1
        }

        var deep = 0
        let result = []
        function x(array){
            deep++
            let result = []
            for (let i of array){
                if (i.__proto__ === Array.prototype){
                    if (!rec_array){
                        result.push(callbackfn(i))
                    }else {
                        result.push(x(i))    
                    }                    
                }else {
                    let current = callbackfn(i)
                    let res;
                    if (new List(String(current)).contains(".")){
                        let var1 = true
                        let n = String(current).split(".")[0]
                        let f = String(current).split(".")[1]
                        let f_len = String(current).split(".")[1].length
                        if (f_len < max_float){
                            for (let j = 0; j < max_float - f_len; j++){
                                f += "0"
                            }
                            
                            var1 = false
                        }else if (f_len > max_float){
                            for (let j = 0; j < f_len - max_float; j++){
                                f = f.slice(0, f.length - 1)
                            }
                        }

                        if (var1 === true){
                            res = parseFloat(n + "." + f)
                        }else {
                            res = n + "." + f
                        }
                        
                    }else {
                        res = current
                    }
                    result.push(res)
                }
            }
            return result
        }
        for (let i of this.#array){
            result.push(x(i))
        }
        return result
    }

    // 对行的处理
    row_sum(row_index){
        let res = 0
        let temp = List.forflat(this.#array[row_index])
        for (let i of temp){
            if (i && (typeof i === "number")){
                res = math.floatCalc(`${res} + ${i}`)
            }
        }
        return res
    }
    row_sub(row_index){
        let temp = List.forflat(this.#array[row_index])
        let res = temp[0]
        for (let i = 1; i < temp.length; i++){
            if (temp[i] && (typeof temp[i] === "number")){
                res = math.floatCalc(`${res} - ${temp[i]}`)
            }
        }
        return res
    }
    row_mul(row_index){
        let res = this.#array[row_index][0]
        if (!res){
            return res
        }
        let temp = List.forflat(this.#array[row_index])
        for (let i = 1; i < temp.length; i++){
            if (temp[i] && (typeof temp[i] === "number")){
                res = math.floatCalc(`${res} * ${temp[i]}`)
            }
        }
        return res
    }
    row_div(row_index){
        let res = this.#array[row_index][0]
        if (!res){
            return res
        }
        let temp = List.forflat(this.#array[row_index])
        for (let i of temp){
            if (i && (typeof i === "number")){
                res /= i
            }
        }
        return res
    }

    // 对列处理
    col_sum(col_index){
        let res = 0
        let arr = []
        for (let i of this.#array){
            arr.push(i)
        }
        for (let i = 0; i < arr.length; i++){
            arr[i] = List.forflat(arr[i])
        }
        for (let i of arr){
            if (i && (typeof i[col_index] === "number")){
                res = math.floatCalc(`${res} + ${i[col_index]}`)
            }
        }
        return res
    }
    col_sub(col_index){
        let res = this.#array[0][col_index]
        let arr = []
        for (let i of this.#array){
            arr.push(i)
        }
        for (let i = 0; i < arr.length; i++){
            arr[i] = List.forflat(arr[i])
        }
        for (let i = 1; i < arr.length; i++){
            if (arr[i][col_index] && (typeof arr[i][col_index] === "number")){
                
                res = math.floatCalc(`${res} - ${arr[i][col_index]}`)
            }
        }
        return res
    }
    col_mul(col_index){
        let arr = []
        for (let i of this.#array){
            arr.push(i)
        }
        for (let i = 0; i < arr.length; i++){
            arr[i] = List.forflat(arr[i])
        }
        let res = arr[0][col_index]
        if (!res){
            return res
        }
        for (let i = 1; i < arr.length; i++){
            if (arr[i][col_index] && (typeof arr[i][col_index] === "number")){
                res = math.floatCalc(`${res} * ${arr[i][col_index]}`)
            }
        }
        return res
    }
    col_div(col_index){
        let arr = []
        for (let i of this.#array){
            arr.push(i)
        }
        for (let i = 0; i < arr.length; i++){
            arr[i] = List.forflat(arr[i])
        }
        let res = arr[0][col_index]
        if (!res){
            return res
        }
        for (let i = 1; i < arr.length; i++){
            if (arr[i][col_index] && (typeof arr[i][col_index] === "number")){
                res /= arr[i][col_index]
            }
        }
        return res
    }

    sum(){
        let res = 0
        let arr = List.forflat(this.#array)
        
        for (let i of arr){
            res = math.floatCalc(`${res} + ${i}`)
        }
        return res
    }
    multiple(){
        let arr = List.forflat(this.#array)
        let res = arr[0]
        for (let i = 1; i < arr.length; i++){
            res = math.floatCalc(`${res} * ${arr[i]}`)
        }
        return res
    }

    push(...array){
        if (array.__proto__ != Array.prototype){
            throw new Error("\"array\" must be a Array")
        }
        for (let i of array){
            this.#array.push(i)
        }
    }
    pop(){
        return this.#array.pop()
    }
    
}


// 链表
class Node{
    constructor(element){
        this.value = element;
        this.next = null;
    }
}

class LinkedList{
    constructor(element){

        if (element && typeof element[Symbol.iterator] === "function") {
            this.size = 0;
            this.head = null;
            let node;
            for (let i of element) {
                if (!this.head) {
                    this.head = new Node(i);
                    node = this.head;
                }else {
                    node.next = new Node(i);
                    node = node.next;
                }
                this.size++;
            }
        }else {
            element = element && element.__proto__ != Node.prototype?
            new Node(element): element;
            this.head = !element? null: element;
            this.size = !element? 0: 1;
        }
    }

    // 查
    getNode(index){
        if (index < 0 || index >= this.size){
            throw new Error("index out of range...");
        }
        let current = this.head;
        for (let i = 0; i < index; i++){
            current = current.next;
        }
        return current;
    }

    // 增
    append(obj){
        obj = obj.__proto__ === Node.prototype? obj: new Node(obj);
        if (!this.size){
            this.head = obj;
            this.size++;
        }else {
            this.getNode(this.size - 1).next = obj;
            this.size++;
        }
    }

    appendAt(index, element){
        if (index < 0 || index > this.size){
            throw new Error("index out of range...");
        }
        element = element.__proto__ === Node.prototype? element: new Node(element);
        // 链表长度为0，直接添加在后面
        if (!this.size){
            this.head = element;
            this.size++;
        }else {
            // 如果添加在最后面
            if (index === this.size - 1){
                this.getNode(index).next = element;
                this.size++;
            }else {
                element.next = this.getNode(index + 1);
                this.getNode(index).next = element;
                this.size++;

            }
            
        }
    }

    // 删
    remove(index){
        if (!index) {
            this.head = null;
            this.size = 0;
            return;
        }
        this.getNode(index - 1).next = this.getNode(index).next;
        this.size--;
    }

    clear() {
        this.head = null;
        this.size = 0;
    }

    show(){
        let res = "LinkedList { head: ";
        if (this.head === null){
            res += "null, size: 0 }";
            return res;
        }
        function showNode(node){
            let result = "Node { value: ";
            result += String(node.value);
            if (node.next === null){
                result += ", next: null }";
                return result;
            }
            result += ", next: "
            result += showNode(node.next);
            return result;
        }
        res += showNode(this.getNode(0)) + ", size: " + String(this.size) + " }"
        return res;
    }

    face() {
        if (!this.size) {
            return "(head)"
        }
        let res = "(head) -> ";
        let node = this.head;
        res += "(" + String(node.value) + ") -> ";
        while (node.next != null) {
            node = node.next;
            res += "(" + String(node.value) + ") -> ";
            
        }
        return res.slice(0, res.length - 3);
    }
}


class CreateData{

    static createName(eng, number, firstNames) {
        if (eng) {
            let res = new List();
            let lastName = !firstNames?[

                            'King', 'Pope', 'Stuart', 'Prior', 'Henry', 
                            'Georget', 'Farmer', 'Carter', 'Smith', 
                            'Trnuer', 'Cook', 'Baker', 'Taylor', 
                            'London', 'Washington', 'Son', 'Johnson', 
                            'Tomson', 'Robinson', 'Jameson', 'Strong', 
                            'Little', 'Long', 'Short', 'Jack', 
                            'Frank', 'Mark', 'Charles', 'Black', 
                            'White', 'Brown', 'Green', 'Fox', 
                            'Cock', 'Wolf', 'Hill', 'Waters', 
                            'Lake', 'Bush', 'Wood', 'Flower'

                            ]: firstNames;
            
            let firstName = function () {
                let len = Random.randint(3, 5);
                let res = []
                for (let i = 0; i < len; i++) {
                    res += MyTools.chr(97 + Random.randint(0, 25));
                }
                return res;
            }

            for (let i = 0; i < number; i++) {
                let f = firstName();
                let r = f[0].toUpperCase() + f.slice(1, f.length) + "·" + Random.extract(1, new List(lastName))
                if (!res.contains(r)) {
                    res.append(r);
                }
            }
            return res.array();
        }else {
            let firstName = !firstNames? "安赵钱孙李周吴郑王邱张杜黄罗谭万方蒋谢尹余董蔡宋宛肖冯陈何沈钟虞廖匡曾": firstNames;

            if (!Random.randint(1, 1)) {
                let lastName = "芳方婷玲珊静英燕艳敏琳倩婧菁菲悦璐然芹意莞若佳妃红东刚智志洋涛峰君";
                let res = new List();
                for (let i = 0; i < number; i++) {
                    let r = Random.randChoice(new List(firstName)) + Random.randChoice(new List(lastName));
                    if (!res.contains(r)) {
                        res.append(r)
                    }
                }
                return res.array();
            }else {
                let thenName = "文少伟倩小晓佳珊然本秀兰竹大婷欣卓语雨一亦艺雪旭建成"
                let lastName = "芳方婷玲珊静英燕艳敏琳倩婧菁菲悦璐然芹意莞若佳妃红东刚智志洋涛峰君";
                let res = new List();
                for (let i = 0; i < number; i++) {
                    let r = Random.randChoice(new List(firstName)) + Random.randChoice(new List(thenName)) + Random.randChoice(new List(lastName));
                    if (!res.contains(r)) {
                        res.append(r)
                    }
                }
                return res.array();
            }
        }
    }


    static createNumber(number_length) {
        let res = "";
        res += String(Random.randint(1, 9))
        for (let i = 0; i < number_length - 1; i++) {
            res += String(Random.randint(0, 9))
        }
        return res;
    }

    static createEmail(type, number) {
        // function(type, number)
        // 当type的首元素为函数时，第二个元素将为类型'qq' 或 "163"
        // 函数返回type[0]()的结果加上指定类型的后缀
        // 如: ([func(), "163"], 3)

        // 当type[0]为类型时，第二个参数将为数字的长度
        // 函数返回对应长度数字加上指定类型的后缀

        // number为返回元素的个数
        if ((typeof type[0]) === "function") {
            let res = []
            let t = type[1]
            for (let i = 0; i < number; i++) {
                res.push(type[0]() + (t === "qq"? "@qq.com": "@163.com"));
            }
            return res;
        }
        let types = ["qq", "163"]
        if (type[0] === "qq") {
            let len = type[1];
            let res = new List();
            for (let i = 0; i < number; i++) {
                let r = CreateData.createNumber(len) + "@qq.com";
                if (!res.contains(r)) {
                    res.append(r);
                }
            }
            return res.array();
        }else if (type[0] === "163") {
            let len = type[1];
            let res = new List();
            for (let i = 0; i < number; i++) {
                let r = CreateData.createNumber(len) + "@163.com";
                if (!res.contains(r)) {
                    res.append(r);
                }
            }
            return res.array();
        }
    }
}

const Stack = (function() {
    let __wm = new WeakMap();
    return class Stack {
        constructor() {
            __wm.set(this, []);
        }

        push(ele) {
            __wm.get(this).push(ele);
        }

        pop() {
            return __wm.get(this).pop();
        }

        peek() {
            return __wm.get(this)[0];
        }

        isEmpty() {
            return !__wm.get(this).length
        }

        clear() {
            __wm.set(this, []);
        }

        size() {
            return __wm.get(this).length;
        }
    }
})()

class Queue {
    #queue
    constructor() {
        this.#queue = [];
    }

    enqueue(ele) {
        this.#queue.push(ele);
    }

    dequeue() {
        return this.#queue.shift();
    }

    front() {
        return this.#queue[0];
    }

    isEmpty() {
        return !this.#queue.length;
    }

    size() {
        return this.#queue.length;
    }

    toString() {
        return new List(this.#queue).showItems();
    }
}

// exports = {
//     MyTools,
//     List,
//     math,
//     Random,
//     LinkedList,
//     Node
// }
export {MyTools, math, List, Random, Matrix, Node, LinkedList, CreateData, Stack, Queue};
